package com.flute.icrawler.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.flute.icrawler.app.processor.check.CheckConfigProcessor;
import com.flute.icrawler.app.processor.extractor.ExtractorHTML;
import com.flute.icrawler.app.processor.fetch.FetchHttp;
import com.flute.icrawler.app.processor.store.LocalMirrorStore;
import com.flute.icrawler.app.task.entity.CrawlTask;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class CrawlConfigUtil {

	private static XStream xstream = null;

	private static Logger logger = LoggerFactory
			.getLogger(CrawlConfigUtil.class);

	static {
		init();
	}

	/**
	 * 
	 */
	private static void init() {
		xstream = new XStream(new DomDriver());
		xstream.alias("crawl-config", CrawlConfig.class);
		xstream.alias("url", Url.class);

		xstream.alias("update", Update.class);
		xstream.alias("bdb", Bdb.class);
		xstream.alias("policys", Policys.class);

		xstream.alias("regurl", RegUrl.class);
		xstream.alias("item", Item.class);

		xstream.addImplicitCollection(RegUrl.class, "items");
		xstream.addImplicitCollection(Policys.class, "policys", "policy",
				Policy.class);
		xstream.addImplicitCollection(Policy.class, "adjustpolicys",
				"adjust-policy", AdjustPolicy.class);

		xstream.useAttributeFor("enabled", Boolean.class);

		xstream.useAttributeFor(Policy.class, "scheduler");
		xstream.useAttributeFor(Policy.class, "granularity");
		xstream.useAttributeFor(AdjustPolicy.class, "time");
		xstream.useAttributeFor(AdjustPolicy.class, "interval");
	}

	/**
	 * 加载配置文件
	 * 
	 * @param filePath
	 *            配置文件的绝对路径
	 */
	public static CrawlConfig newCrawlConfig(String filePath) {
		try {
			return (CrawlConfig) xstream.fromXML(new FileInputStream(filePath));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

	}

	public static void buildFile(Object object, String filePath) {
		FileOutputStream outputStream = null;
		try {
			createFile(filePath);

			outputStream = new FileOutputStream(filePath);
			OutputStreamWriter writer = new OutputStreamWriter(outputStream,
					Charset.forName("gb2312"));
			writer.write("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");

			xstream.toXML(object, writer);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
				outputStream = null;

			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 * 将指定的配置对象转换成XML配置文件
	 * 
	 * @param config
	 *            配置对象
	 * @param filePath
	 *            生成配置文件的相对路径
	 * 
	 * @param interval
	 *            运行周期
	 */
	public static void buildConfigFile(CrawlConfig config, String filePath,
			String interval) {
		buildConfigFile(config, filePath, interval, "1", "false");
	}

	/**
	 * 将指定的配置对象转换成XML配置文件
	 * 
	 * @param config
	 *            配置对象
	 * @param filePath
	 *            生成配置文件的路径 同时也是任务的名称
	 * @param interval
	 *            任务运行周期
	 * @param nodesNeed
	 *            启动节点个数
	 * @param scalable
	 *            是否需要浮动 yes no
	 */
	public static void buildConfigFile(CrawlConfig config, String filePath,
			String interval, String nodesNeed, String scalable) {

		try {
			// 生成任务配置文件
			String path = CrawlTask.TASK_LIST + File.separator + filePath
					+ File.separator + CrawlTask.CONFIG_FILENAME;

			config.setTaskName(filePath);

			buildFile(config, path);

			// 生成任务描述文件
			Properties properties = new Properties();
			// 设置周期
			properties.setProperty(CrawlTask.TASK_DES_INTERVAL, interval);
			// 设置启动节点数
			properties.setProperty(CrawlTask.TASK_DES_NODECOUNT, nodesNeed);
			// 设置是否可以浮动
			properties.setProperty(CrawlTask.TASK_DES_SCALABLE, scalable);

			String infoFileName = CrawlTask.TASK_LIST + File.separator
					+ filePath + File.separator + CrawlTask.INFO_FILENAME;
			properties.storeToXML(new FileOutputStream(infoFileName), "",
					"gb2312");

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 获取基础配置
	 * 
	 * @return
	 */
	public static CrawlConfig getBaseConfig() {

		String baseFilePath;
		try {
			baseFilePath = getClassLoader().getResource(
					CrawlTask.CONFIG_FILENAME).getFile();
			return newCrawlConfig(baseFilePath);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	public static void main(String[] args) {

		String startmonitor = "";

		String deep = "1";
		CrawlConfig newConfig = CrawlConfigUtil.getBaseConfig();
		
		CrawlConfigUtil.buildConfigFile(newConfig, "2name", "100");
		
		
		System.out.println(newConfig.getUrl().getResultDealThreadCount());

		System.out.println(newConfig.getFrameworkPrintInterval());

		if ("yes".equalsIgnoreCase(startmonitor)) {
			newConfig.setStartHardwareAdjust(0);
		} else {
			newConfig.setStartHardwareAdjust(1);
		}

		try {
			newConfig.getUrl().setDepth(new Integer((deep)));

		} catch (NumberFormatException numberFormatException) {
			numberFormatException.printStackTrace();
		}

		newConfig.setTaskName("test");
		newConfig.setNeedAppend(0);

		newConfig.getUrl().addSeed("http://www.163.com");

		ProcessorConfig processorConfig = new ProcessorConfig();

		processorConfig.addProcessor(new CheckConfigProcessor());

		FetchHttp fetchHttp = new FetchHttp();
		fetchHttp.addDependencyID(1);
		fetchHttp.addDependencyID(2);
		processorConfig.addProcessor(fetchHttp);

		processorConfig.addProcessor(new ExtractorHTML());

		processorConfig.addProcessor(new LocalMirrorStore());

		newConfig.setProcessorConfig(processorConfig);
	

		CrawlConfigUtil.buildConfigFile(newConfig, "1name", "100");

		buildFile(fetchHttp, CrawlTask.TASK_LIST + File.separator+fetchHttp.getClass().getSimpleName() + "-"
				+ fetchHttp.ID + ".xml");

	}

	/**
	 * 
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private static ClassLoader getClassLoader() throws IllegalAccessException,
			InvocationTargetException {
		Method method = null;
		try {
			method = Thread.class.getMethod("getContextClassLoader",
					(Class[]) null);
		} catch (NoSuchMethodException e) {
			return null;
		}
		return (ClassLoader) method.invoke(Thread.currentThread(),
				(Object[]) null);
	}

	/**
	 * 创建文件及其包含的文件夹
	 * 
	 * @param strFile
	 * @throws IOException
	 */
	private static void createFile(String strFile) throws IOException {
		File file = new File(strFile);

		File fileDirs = new File(file.getParent());
		if (!fileDirs.exists()) {
			fileDirs.mkdirs();
		}

		if (!file.exists()) {

			file.createNewFile();
		}
	}
}
